package server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * ServerController: Manage a server.
 */
public final class ServerController implements ServerInterface, Runnable {

    private Thread thisServer;
    private int serverPort;
    private int serverDataPort;
    private ServerSocket serverSocket;
    private boolean stop = false;
    private ExecutorService threadsPool;

    /**
     * Constructor.
     *
     * @param serverPort Indicates the port to listen.
     */
    public ServerController(int serverPort) {
        this.serverSocket = null;
        this.thisServer = null;
        this.serverPort = serverPort;
        threadsPool = Executors.newCachedThreadPool();
    }

    /**
     * run() method for thread support. Listening for new connections on the
     * server port.
     */
    @Override
    public void run() {
        synchronized (this) {
            this.thisServer = Thread.currentThread();
        }
        try {
            this.serverSocket = new ServerSocket(this.serverPort);
            while (!this.stop) {
                Socket clientSocket = null;
                try {
                    clientSocket = this.serverSocket.accept(); //Wait for clients.
                } catch (IOException ex) {
                    System.err.println("Error accepting a new client.");
                }
                this.threadsPool.execute(new ClientController(clientSocket)); //Create a new thread to manage the new client.
            }
            this.threadsPool.shutdown();
            System.out.println("Server shutdown.");
        } catch (IOException ex) {
            System.err.println("Error opening the server socket.");
        }

    }

    @Override
    public synchronized void shutdown() { //Synchronized to avoid problems stoping the client from diferents threads.
        this.stop = true;
        try {
            this.serverSocket.close();
        } catch (IOException ex) {
            Logger.getLogger(ServerController.class
                    .getName()).log(Level.SEVERE, null, ex);
        }
    }

}
